<?php
namespace service;

use think\Cache;
use think\Log;

/**
 * 微信小程序服务
 */
class WechatMicroProgramService
{
	protected static $baseUrl = 'https://api.weixin.qq.com';

	/**
	 * 公共参数
	 * @var [type]
	 */
	public static function getCommonParams()
	{
		return [
			'appid'  => \think\Env::get('WECHATMP.APP_ID'),
			'secret' => \think\Env::get('WECHATMP.APP_SECRET'),
		];
	}

	/**
	 * 获取通信令牌
	 * @Author   FW
	 * @DateTime 2024-03-14
	 * @Email    123763712@qq.com
	 * @return   [type]           [description]
	 */
	public static function getAccessToken()
	{
		$accessToken = \think\Cache::get('wechatMicroProgramAccessToken');
		if ( empty($accessToken) ) {
			$params = array_merge([
				'grant_type'=> 'client_credential'
			] , static::getCommonParams());
			$res = self::curlRequest( static::$baseUrl . '/cgi-bin/token?' . static::buildParams($params));

			if ( isset($res['access_token']) && isset($res['expires_in']) ) {
				$accessToken = $res['access_token'];
				\think\Cache::set('wechatMicroProgramAccessToken' , $accessToken , $res['expires_in']);
			}
		}
		if ( empty($accessToken) ) throw new \Exception('未获取到有效的accessToken');

		return $accessToken;
	}

	/**
	 * 小程序登录
	 * @see https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html
	 * @Author   FW
	 * @DateTime 2021-04-26
	 * @Email    123763712@qq.com
	 * @param    array            $params [description]
	 * @return   [type]                   [description]
	 */
	public static function code2Session ( $js_code )
	{
		try {
			$params = array_merge([
				'js_code'   => $js_code,
				'grant_type'=> 'authorization_code'
			] , static::getCommonParams());

			// return [
			// 	"openid"      => "iGfu_20393djHHgduqRe2iPmAzx12",
			// 	"session_key" => md5("xxxxxxx"),
			// 	"unionid"     => md5("iGfu_20393djHHgduqRe2iPmAzx12"),
			// 	"errcode"     => 0,
			// 	"errmsg"      => ""
			// ];
			return self::curlRequest( static::$baseUrl . '/sns/jscode2session?' . static::buildParams($params));
		} catch ( \Exception $e ) {
			throw new \Exception($e->getMessage());
		}
	}

	/**
	 * 将code换取用户手机号。
	 * 说明，每个code只能使用一次，code的有效期为5min
	 * @Author   FW
	 * @DateTime 2024-03-14
	 * @Email    123763712@qq.com
	 * @param    [type]           $code [description]
	 * @return   [type]                 [description]
	 */
	public static function getPhoneNumber ( $code , $openid = '' )
	{
		try {
			$params = [
				'code'  => $code,
				'openid'=> $openid
			];
			return self::curlRequest( static::$baseUrl . '/wxa/business/getuserphonenumber?access_token=' . static::getAccessToken(), $params , 'POST');
		} catch ( \Exception $e ) {
			throw new \Exception($e->getMessage());
		}
	}

	/**
	 * 获取小程序码
	 * @https://developers.weixin.qq.com/minigame/dev/api-backend/open-api/qr-code/wxacode.get.html
	 * @Author   FW
	 * @DateTime 2024-04-15
	 * @Email    123763712@qq.com
	 * @return   [type]           [description]
	 */
	public static function getWxaCode ($path , $width = 280)
	{
		try {
			$params = [
				'path'       => $path,
				'width'      => $width,
				'is_hyaline' => false
			];
			return self::curlRequest( static::$baseUrl . '/wxa/getwxacode?access_token=' . static::getAccessToken(), $params , 'POST' , $header = array("content-type: application/object") , true, 5, false );
		} catch ( \Exception $e ) {
			throw new \Exception($e->getMessage());
		}
	}

	/**
	 * 组参
	 * @Author   FW
	 * @DateTime 2024-03-13
	 * @Email    123763712@qq.com
	 * @param    [type]           $params [description]
	 * @return   [type]                   [description]
	 */
	public static function buildParams($params)
	{
		if ( !is_array($params) || empty($params) ) return '';

		return http_build_query($params);
	}


	/**
	 * @Description: curl请求
	 * @Author: FW
	 * @param $url
	 * @param null $data
	 * @param string $method
	 * @param array $header
	 * @param bool $https
	 * @param int $timeout
	 * @return mixed
	 */
	public static function curlRequest($url, $data=null, $method='get', $header = array("content-type: application/json"), $https=true, $timeout = 5 , $josn2Arr = true){
	    $method = strtoupper($method);
	    $ch = curl_init();//初始化
	    curl_setopt($ch, CURLOPT_URL, $url);//访问的URL
	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//只获取页面内容，但不输出
	    if($https){
	        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//https请求 不验证证书
	        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//https请求 不验证HOST
	    }

	    if ( $method != "GET" ) {
	        if( $method == 'POST' ){
	            curl_setopt($ch, CURLOPT_POST, true);//请求方式为post请求
	            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));//请求数据
	        }
	        if ( $method == 'PUT' || strtoupper($method) == 'DELETE' ) {
	            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); //设置请求方式
	        }

			Log::info('curl send data:' .  json_encode($data));
	    }
	    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
	    curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //模拟的header头
	    //curl_setopt($ch, CURLOPT_HEADER, false);//设置不需要头信息


	    $result = curl_exec($ch);//执行请求
	    curl_close($ch);//关闭curl，释放资源

	    if ( $josn2Arr && is_string($result) ) {
	    	$result = json_decode($result,true);

	    	if ( json_last_error() > 0 ) {
	    		return [];
	    	}
	    }
	    Log::info('curl responde data:' .  json_encode($result));
	    return $result;
	}
}